package util;

import com.sun.org.apache.xml.internal.security.algorithms.SignatureAlgorithm;
import io.jsonwebtoken.*;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.boot.context.properties.ConfigurationProperties;

import java.util.Date;

//从application.yml中的jwt.config自动获取对应属性的值
//也就是将jwt.config中的值自动映射到key和ttl属性中,从而可以一次性赋值,而不用一个一个赋值
//重点:谁调用,就从谁的application.yml中获取
@ConfigurationProperties("jwt.config")
public class JwtUtil {
    //@Value("${jwt.config.key}")  (或者)
    private String key;

    private long ttl;

    public String getKey() {
        return key;
    }

    public void setKey(String key) {
        this.key = key;
    }

    public long getTtl() {
        return ttl;
    }

    public void setTtl(long ttl) {
        this.ttl = ttl;
    }

    /**
     * 生成token :用来识别用户信息,鉴权的
     * 将用户必要信息加密后返回token字符串给客户端,客户端下次访问时,将token写到
     * 请求头中进行访问,这样后端就可以识别请求的用户信息,从而实现无状态的访问
     * @param id 用户id
     * @param name 用户姓名
     * @param roles 用户角色
     * @return
     */
    public String generateToken(String id, String name, String roles) {
        //获取当前时间毫秒数
        long currentTimeMillis = System.currentTimeMillis();
        //设置失效时间
        long expirationTimeMillis = currentTimeMillis+1000*60*ttl;

        String token = Jwts
                .builder()  //获取JWT-token的构建工具
                //设置自定义载荷(单个)  自定义载荷要放在固定载荷之前,也要放在设置载荷时间之前,不然固定载荷和设置时间无效
                //自定义载荷需要放置到有效时间之前
                .claim("role",roles)
                .setId(id)  //设置载荷部分(固定载荷)的键值对
                .setSubject(name)  //设置载荷部分(固定载荷)的键值对
                .setIssuedAt(new Date(currentTimeMillis)) //设置token的创建时间
                .setExpiration(new Date(expirationTimeMillis))  //设置token的失效时间
                .signWith(io.jsonwebtoken.SignatureAlgorithm.HS256, key)  //设置密钥签名方式(加密方式),以及密钥的值(加盐加密,也就是盐的值)
                .compact();//返回token
        return token;
    }

    /**
     * 解析token  我们自己从返回的body中获取自己需要的值
     * @param token
     * @return
     */
    public Claims parserToken(String token) {
        try {
            Claims body = Jwts
                    .parser()  //获取token解析器
                    .setSigningKey(key)  //指定解析密钥(盐)
                    .parseClaimsJws(token)  //解析token
                    .getBody();//获取载荷部分
            return body;
        } catch (Exception e) {
            e.printStackTrace();
            return null;
        }
    }
}
